<?php
/**
 * CodeIgniter
 *
 * An open source application development framework for PHP
 *
 * This content is released under the MIT License (MIT)
 *
 * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 *
 * @package	CodeIgniter
 * @author	EllisLab Dev Team
 * @copyright	Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
 * @copyright	Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
 * @license	http://opensource.org/licenses/MIT	MIT License
 * @link	https://codeigniter.com
 * @since	Version 1.0.0
 * @filesource
 */
defined ( 'BASEPATH' ) or exit ( 'No direct script access allowed' );

/**
 * System Initialization File
 *
 * Loads the base classes and executes the request.
 *
 * @package CodeIgniter
 * @subpackage CodeIgniter
 * @category Front-controller
 * @author EllisLab Dev Team
 * @link https://codeigniter.com/user_guide/
 */

/**
 * CodeIgniter Version
 *
 * @var string
 *
 */
const CI_VERSION = '3.1.6';

/*
 * ------------------------------------------------------
 * Load the framework constants
 * ------------------------------------------------------
 */
if (file_exists ( APPPATH . 'config/' . ENVIRONMENT . '/constants.php' )) {
	require_once (APPPATH . 'config/' . ENVIRONMENT . '/constants.php');
}
if (file_exists ( APPPATH . 'config/constants.php' )) {
	require_once (APPPATH . 'config/constants.php');
}

/*
 * ------------------------------------------------------
 * Load the global functions
 * ------------------------------------------------------
 */
require_once (BASEPATH . 'core/Common.php');

/*
 * ------------------------------------------------------
 * Security procedures
 * ------------------------------------------------------
 */

if (! is_php ( '5.4' )) {
	ini_set ( 'magic_quotes_runtime', 0 );
	
	if (( bool ) ini_get ( 'register_globals' )) {
		$_protected = array (
				'_SERVER',
				'_GET',
				'_POST',
				'_FILES',
				'_REQUEST',
				'_SESSION',
				'_ENV',
				'_COOKIE',
				'GLOBALS',
				'HTTP_RAW_POST_DATA',
				'system_path',
				'application_folder',
				'view_folder',
				'_protected',
				'_registered' 
		);
		
		$_registered = ini_get ( 'variables_order' );
		foreach ( array (
				'E' => '_ENV',
				'G' => '_GET',
				'P' => '_POST',
				'C' => '_COOKIE',
				'S' => '_SERVER' 
		) as $key => $superglobal ) {
			if (strpos ( $_registered, $key ) === FALSE) {
				continue;
			}
			
			foreach ( array_keys ( $$superglobal ) as $var ) {
				if (isset ( $GLOBALS [$var] ) && ! in_array ( $var, $_protected, TRUE )) {
					$GLOBALS [$var] = NULL;
				}
			}
		}
	}
}

/*
 * ------------------------------------------------------
 * Define a custom error handler so we can log PHP errors
 * ------------------------------------------------------
 */
set_error_handler ( '_error_handler' );
set_exception_handler ( '_exception_handler' );
register_shutdown_function ( '_shutdown_handler' );

/*
 * ------------------------------------------------------
 * Set the subclass_prefix
 * ------------------------------------------------------
 *
 * Normally the "subclass_prefix" is set in the config file.
 * The subclass prefix allows CI to know if a core class is
 * being extended via a library in the local application
 * "libraries" folder. Since CI allows config items to be
 * overridden via data set in the main index.php file,
 * before proceeding we need to know if a subclass_prefix
 * override exists. If so, we will set this value now,
 * before any classes are loaded
 * Note: Since the config file data is cached it doesn't
 * hurt to load it here.
 */
if (! empty ( $assign_to_config ['subclass_prefix'] )) {
	get_config ( array (
			'subclass_prefix' => $assign_to_config ['subclass_prefix'] 
	) );
}

/*
 * ------------------------------------------------------
 * Should we use a Composer autoloader?
 * ------------------------------------------------------
 */
if ($composer_autoload = config_item ( 'composer_autoload' )) {
	if ($composer_autoload === TRUE) {
		file_exists ( APPPATH . 'vendor/autoload.php' ) ? require_once (APPPATH . 'vendor/autoload.php') : log_message ( 'error', '$config[\'composer_autoload\'] is set to TRUE but ' . APPPATH . 'vendor/autoload.php was not found.' );
	} elseif (file_exists ( $composer_autoload )) {
		require_once ($composer_autoload);
	} else {
		log_message ( 'error', 'Could not find the specified $config[\'composer_autoload\'] path: ' . $composer_autoload );
	}
}

/*
 * ------------------------------------------------------
 * Start the timer... tick tock tick tock...
 * ------------------------------------------------------
 */
$BM = & load_class ( 'Benchmark', 'core' );
$BM->mark ( 'total_execution_time_start' );
$BM->mark ( 'loading_time:_base_classes_start' );

/*
 * ------------------------------------------------------
 * Instantiate the hooks class
 * ------------------------------------------------------
 */
$EXT = & load_class ( 'Hooks', 'core' );

/*
 * ------------------------------------------------------
 * Is there a "pre_system" hook?
 * ------------------------------------------------------
 */
$EXT->call_hook ( 'pre_system' );

/*
 * ------------------------------------------------------
 * Instantiate the config class
 * ------------------------------------------------------
 *
 * Note: It is important that Config is loaded first as
 * most other classes depend on it either directly or by
 * depending on another class that uses it.
 *
 */
$CFG = & load_class ( 'Config', 'core' );

// Do we have any manually set config items in the index.php file?
if (isset ( $assign_to_config ) && is_array ( $assign_to_config )) {
	foreach ( $assign_to_config as $key => $value ) {
		$CFG->set_item ( $key, $value );
	}
}

/*
 * ------------------------------------------------------
 * Important charset-related stuff
 * ------------------------------------------------------
 *
 * Configure mbstring and/or iconv if they are enabled
 * and set MB_ENABLED and ICONV_ENABLED constants, so
 * that we don't repeatedly do extension_loaded() or
 * function_exists() calls.
 *
 * Note: UTF-8 class depends on this. It used to be done
 * in it's constructor, but it's _not_ class-specific.
 *
 */
$charset = strtoupper ( config_item ( 'charset' ) );
ini_set ( 'default_charset', $charset );

if (extension_loaded ( 'mbstring' )) {
	define ( 'MB_ENABLED', TRUE );
	// mbstring.internal_encoding is deprecated starting with PHP 5.6
	// and it's usage triggers E_DEPRECATED messages.
	@ini_set ( 'mbstring.internal_encoding', $charset );
	// This is required for mb_convert_encoding() to strip invalid characters.
	// That's utilized by CI_Utf8, but it's also done for consistency with iconv.
	mb_substitute_character ( 'none' );
} else {
	define ( 'MB_ENABLED', FALSE );
}

// There's an ICONV_IMPL constant, but the PHP manual says that using
// iconv's predefined constants is "strongly discouraged".
if (extension_loaded ( 'iconv' )) {
	define ( 'ICONV_ENABLED', TRUE );
	// iconv.internal_encoding is deprecated starting with PHP 5.6
	// and it's usage triggers E_DEPRECATED messages.
	@ini_set ( 'iconv.internal_encoding', $charset );
} else {
	define ( 'ICONV_ENABLED', FALSE );
}

if (is_php ( '5.6' )) {
	ini_set ( 'php.internal_encoding', $charset );
}

/*
 * ------------------------------------------------------
 * Load compatibility features
 * ------------------------------------------------------
 */

require_once (BASEPATH . 'core/compat/mbstring.php');
require_once (BASEPATH . 'core/compat/hash.php');
require_once (BASEPATH . 'core/compat/password.php');
require_once (BASEPATH . 'core/compat/standard.php');

/*
 * ------------------------------------------------------
 * Instantiate the UTF-8 class
 * ------------------------------------------------------
 */
$UNI = & load_class ( 'Utf8', 'core' );

/*
 * ------------------------------------------------------
 * Instantiate the URI class
 * ------------------------------------------------------
 */
$URI = & load_class ( 'URI', 'core' );

/*
 * ------------------------------------------------------
 * Instantiate the routing class and set the routing
 * ------------------------------------------------------
 */

$RTR = & load_class ( 'Router', 'core', isset ( $routing ) ? $routing : NULL );

/*
 * ------------------------------------------------------
 * Instantiate the output class
 * ------------------------------------------------------
 */
$OUT = & load_class ( 'Output', 'core' );

/*
 * ------------------------------------------------------
 * Is there a valid cache file? If so, we're done...
 * ------------------------------------------------------
 */
if ($EXT->call_hook ( 'cache_override' ) === FALSE && $OUT->_display_cache ( $CFG, $URI ) === TRUE) {
	exit ();
}

/*
 * -----------------------------------------------------
 * Load the security class for xss and csrf support
 * -----------------------------------------------------
 */
$SEC = & load_class ( 'Security', 'core' );

/*
 * ------------------------------------------------------
 * Load the Input class and sanitize globals
 * ------------------------------------------------------
 */
$IN = & load_class ( 'Input', 'core' );

/*
 * ------------------------------------------------------
 * Load the Language class
 * ------------------------------------------------------
 */
$LANG = & load_class ( 'Lang', 'core' );

/*
 * ------------------------------------------------------
 * Load the app controller and local controller
 * ------------------------------------------------------
 *
 */

// Load the base controller class
require_once BASEPATH . 'core/Controller.php';

/**
 * Reference to the CI_Controller method.
 *
 * Returns current CI instance object
 *
 * @return CI_Controller
 */
function &get_instance() {
	return CI_Controller::get_instance ();
}

if (file_exists ( APPPATH . 'core/' . $CFG->config ['subclass_prefix'] . 'Controller.php' )) {
	
	require_once APPPATH . 'core/' . $CFG->config ['subclass_prefix'] . 'Controller.php';
}

// Set a mark point for benchmarking
$BM->mark ( 'loading_time:_base_classes_end' );

/*
 * ------------------------------------------------------
 * Sanity checks
 * ------------------------------------------------------
 *
 * The Router class has already validated the request,
 * leaving us with 3 options here:
 *
 * 1) an empty class name, if we reached the default
 * controller, but it didn't exist;
 * 2) a query string which doesn't go through a
 * file_exists() check
 * 3) a regular request for a non-existing page
 *
 * We handle all of these as a 404 error.
 *
 * Furthermore, none of the methods in the app controller
 * or the loader class can be called via the URI, nor can
 * controller methods that begin with an underscore.
 */

$e404 = FALSE;
$class = ucfirst ( $RTR->class );
// $finalclass="\\".$CFG->config['default_namaspace']."\\".$class;

if (preg_match ( "/[\'.,:;*?~`!@#$%^&+=)(<>{}]|\]|\[|\/|\\\|\"|\|/", $class )) { // 不允许特殊字符
	$class = ucfirst ( $RTR->default_controller );
}
$finalclass = $class;
$method = $RTR->method;
$method=str_replace('.html', '', $method);
$method == 'default' && $method = 'index';
if (strpos ( $class, '_' ) != FALSE) {
	$arrtemp = explode ( '_', $class );
	$RTR->directory = $arrtemp [0] . DIRECTORY_SEPARATOR;
}
if(isset($CFG->config['dir_name'])){
	
	if($class==ucfirst($CFG->config['dir_name'])){
		$class="Index";
	}
}

if (empty ( $class ) or ! file_exists ( APPPATH . 'controllers/' . $RTR->directory . $class . '.php' )) {
	
	$e404 = TRUE;
} else {
	require_once (APPPATH . 'controllers/' . $RTR->directory . $class . '.php');
	
	if (! class_exists ( $class, FALSE ) or $method [0] === '_' or method_exists ( 'CI_Controller', $method )) {
		
		$e404 = TRUE;
	} elseif (method_exists ( $class, '_remap' )) {
		$params = array (
				$method,
				array_slice ( $URI->rsegments, 2 ) 
		);
		$method = '_remap';
	} elseif (! method_exists ( $class, $method )) {
	
		$e404 = TRUE;
	} /**
	 * DO NOT CHANGE THIS, NOTHING ELSE WORKS!
	 *
	 * - method_exists() returns true for non-public methods, which passes the previous elseif
	 * - is_callable() returns false for PHP 4-style constructors, even if there's a __construct()
	 * - method_exists($class, '__construct') won't work because CI_Controller::__construct() is inherited
	 * - People will only complain if this doesn't work, even though it is documented that it shouldn't.
	 *
	 * ReflectionMethod::isConstructor() is the ONLY reliable check,
	 * knowing which method will be executed as a constructor.
	 */
	elseif (! is_callable ( array (
			$class,
			$method 
	) )) {
		$reflection = new ReflectionMethod ( $class, $method );
		if (! $reflection->isPublic () or $reflection->isConstructor ()) {
			$e404 = TRUE;
		}
	}
}

if ($e404) {

	if (! empty ( $RTR->routes ['404_override'] )) {
		if (sscanf ( $RTR->routes ['404_override'], '%[^/]/%s', $error_class, $error_method ) !== 2) {
			$error_method = 'index';
		}
		
		$error_class = ucfirst ( $error_class );
		
		if (! class_exists ( $error_class, FALSE )) {
			if (file_exists ( APPPATH . 'controllers/' . $RTR->directory . $error_class . '.php' )) {
				require_once (APPPATH . 'controllers/' . $RTR->directory . $error_class . '.php');
				$e404 = ! class_exists ( $error_class, FALSE );
			}			// Were we in a directory? If so, check for a global override
			elseif (! empty ( $RTR->directory ) && file_exists ( APPPATH . 'controllers/' . $error_class . '.php' )) {
				require_once (APPPATH . 'controllers/' . $error_class . '.php');
				if (($e404 = ! class_exists ( $error_class, FALSE )) === FALSE) {
					$RTR->directory = '';
				}
			}
		} else {
			$e404 = FALSE;
		}
	}
	
	// Did we reset the $e404 flag? If so, set the rsegments, starting from index 1
	if (! $e404) {
		$class = $error_class;
		$method = $error_method;
		
		$URI->rsegments = array (
				1 => $class,
				2 => $method 
		);
	} else {
		
		show_404 ( $RTR->directory . $class . '/' . $method );
	
	}
}

if ($method !== '_remap') {
	$params = array_slice ( $URI->rsegments, 2 );
}

/*
 * ------------------------------------------------------
 * Is there a "pre_controller" hook?
 * ------------------------------------------------------
 */
$EXT->call_hook ( 'pre_controller' );

/*
 * ------------------------------------------------------
 * Instantiate the requested controller
 * ------------------------------------------------------
 */

// Mark a start point so we can benchmark the controller
$BM->mark ( 'controller_execution_time_( ' . $class . ' / ' . $method . ' )_start' );

$CI = new $class ();

/*
 * ------------------------------------------------------
 * Is there a "post_controller_constructor" hook?
 * ------------------------------------------------------
 */
$EXT->call_hook ( 'post_controller_constructor' );

/*
 * ------------------------------------------------------
 * Call the requested method
 * ------------------------------------------------------
 */
call_user_func_array ( array (
		&$CI,
		$method 
), $params );

// Mark a benchmark end point
$BM->mark ( 'controller_execution_time_( ' . $class . ' / ' . $method . ' )_end' );

/*
 * ------------------------------------------------------
 * Is there a "post_controller" hook?
 * ------------------------------------------------------
 */
$EXT->call_hook ( 'post_controller' );

/*
 * ------------------------------------------------------
 * Send the final rendered output to the browser
 * ------------------------------------------------------
 */
if ($EXT->call_hook ( 'display_override' ) === FALSE) {
	$OUT->_display ();
}

/*
 * ------------------------------------------------------
 * Is there a "post_system" hook?
 * ------------------------------------------------------
 */
$EXT->call_hook ( 'post_system' );
